﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;
using System.Data;
using System.Threading;

namespace mstdump_Analyzer
{
    class PortInfoETH : PortInfoInterface
    {
        ArrayList portsArrayList = new ArrayList();
        private bool KEEP_RUNNING; 
        private string OUTPUT_DIR_PATH;
        private bool timeouts = false;
        //
        //----------------------------------------------------
        //
        public PortInfoETH(ref bool KEEP_RUNNING, ref string OUTPUT_DIR_PATH)
        {
            this.KEEP_RUNNING = KEEP_RUNNING;   
            this.OUTPUT_DIR_PATH = OUTPUT_DIR_PATH;
        }
        //
        //----------------------------------------------------
        //
        public DataTable getLeafsPortInfo()
        {
            // create a DataTable
            DataTable table = new DataTable();
            // add columns
            table.Columns.Add("Port#", typeof(double));
            table.Columns.Add("Admin state", typeof(string));
            table.Columns.Add("Operational state", typeof(string));
            table.Columns.Add("Description", typeof(string));
            table.Columns.Add("Mac address", typeof(string));
            table.Columns.Add("MTU", typeof(string));
            table.Columns.Add("Flow-control", typeof(string));
            table.Columns.Add("Actual speed", typeof(string));
            table.Columns.Add("Switchport mode", typeof(string));
            table.Columns.Add("Cable identifier", typeof(string));
            table.Columns.Add("Cable/module type", typeof(string));
            table.Columns.Add("Cable ethernet speed and type", typeof(string));
            table.Columns.Add("Cable vendor", typeof(string));
            table.Columns.Add("Cable cable length", typeof(string));
            table.Columns.Add("Cable revision", typeof(string));
            table.Columns.Add("Cable part number", typeof(string));
            table.Columns.Add("Cable serial number", typeof(string));

            // rx
            table.Columns.Add("RX frames", typeof(long));
            table.Columns.Add("RX unicast frames", typeof(long));
            table.Columns.Add("RX multicast frames", typeof(long));
            table.Columns.Add("RX broadcast frames", typeof(long));
            table.Columns.Add("RX octets", typeof(long));
            table.Columns.Add("RX error frames", typeof(long));
            table.Columns.Add("RX discard frames", typeof(long));
            
            // tx
            table.Columns.Add("TX frames", typeof(long));
            table.Columns.Add("TX unicast frames", typeof(long));
            table.Columns.Add("TX multicast frames", typeof(long));
            table.Columns.Add("TX broadcast frames", typeof(long));
            table.Columns.Add("TX octets", typeof(long));
            table.Columns.Add("TX discard frames", typeof(long));

            // add DataRows.
            for (int i=0 ; i<portsArrayList.Count ;i++)
            {
                PortInfoETHFields pi = (PortInfoETHFields)portsArrayList[i];
                table.Rows.Add(pi.portNum, 
                    pi.adminState, 
                    pi.operationalState,
                    pi.description,
                    pi.MacAddress,
                    pi.MTU,
                    pi.FlowControl,
                    pi.actualSpeed,
                    pi.switchPortMode,
                    pi.identifier,
                    pi.cableModuleType,
                    pi.ethernetSpeedAndType,
                    pi.vendor,
                    pi.cableLength,
                    pi.revision,
                    pi.partNumber,
                    pi.serialNumber,
                    pi.RXFrames,
                    pi.RXUnicastFrames,
                    pi.RXMulticastFrames,
                    pi.RXBroadcastFrames,
                    pi.RXOctets,
                    pi.RXErrorFrames,
                    pi.RXDiscardFrames,
                    pi.TXFrames,
                    pi.TXUnicastFrames,
                    pi.TXMulticastFrames,
                    pi.TXBroadcastFrames,
                    pi.TXOctets,
                    pi.TXDiscardFrames);
            }
            return table;
        }
        //
        //----------------------------------------------------
        //
        public DataTable getSpinesPortInfo()
        {
            return null; 
        }
        //
        //----------------------------------------------------
        //
        public void scanPortInfo(object param)
        {
            string srcFilePath = (string)param;
            if (srcFilePath == null)
                return;
            StreamReader sr = new StreamReader(srcFilePath);
            try
            {
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    if (sr.ReadLine().Contains("port info"))
                    {
                        break;
                    }
                }
                PortInfoETHFields tmpPort = null;
                int index = 0;
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    // read line
                    string line = sr.ReadLine();
                    if (line.Contains("timed out after"))
                    {
                        timeouts = true;
                    }
                    try
                    {
                        // port info
                        if (line.Contains("Eth1"))
                        {
                            tmpPort = new PortInfoETHFields();
                            tmpPort.portNum = 0;
                            string []tmp = Regex.Split(line, "/");
                            if (tmp.Length == 2)
                            {
                                tmpPort.portNum = Int32.Parse(tmp[1]);
                            }
                            if (tmp.Length == 3)
                            {
                                tmpPort.portNum = Int32.Parse(tmp[1]);
                                tmpPort.portNum = tmpPort.portNum + ((double)Int32.Parse(tmp[2]))/10;
                            }
                            
                        }
                        if (line.Contains("Admin state"))
                        {
                            tmpPort.adminState = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("Operational state"))
                        {
                            tmpPort.operationalState = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("Description"))
                        {
                            tmpPort.description = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("Description"))
                        {
                            tmpPort.description = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("Mac address"))
                        {
                            tmpPort.MacAddress = Regex.Split(line, "address:")[1];
                        }
                        if (line.Contains("MTU"))
                        {
                            tmpPort.MTU = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("Flow-control"))
                        {
                            tmpPort.FlowControl = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("Actual speed"))
                        {
                            tmpPort.actualSpeed = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("Switchport mode"))
                        {
                            tmpPort.switchPortMode = Regex.Split(line, ":")[1];
                        }
                        //
                        if (line.Contains("Rx"))
                        {
                            while (KEEP_RUNNING && sr.Peek() >= 0)
                            {
                                // read line
                                line = sr.ReadLine();
                                if (line.Contains("frames"))
                                {
                                    tmpPort.RXFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("unicast frames"))
                                {
                                    tmpPort.RXUnicastFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("multicast frames"))
                                {
                                    tmpPort.RXMulticastFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("broadcast frames"))
                                {
                                    tmpPort.RXBroadcastFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("octets"))
                                {
                                    tmpPort.RXOctets = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("error frames"))
                                {
                                    tmpPort.RXErrorFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("discard frames"))
                                {
                                    tmpPort.RXDiscardFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                    break;
                                }
                            }
                        }
                        //
                        if (line.Contains("Tx"))
                        {
                            while (KEEP_RUNNING && sr.Peek() >= 0)
                            {
                                // read line
                                line = sr.ReadLine();
                                if (line.Contains("frames"))
                                {
                                    tmpPort.TXFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }

                                if (line.Contains("unicast frames"))
                                {
                                    tmpPort.TXUnicastFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("multicast frames"))
                                {
                                    tmpPort.TXMulticastFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("broadcast frames"))
                                {
                                    tmpPort.TXBroadcastFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("octets"))
                                {
                                    tmpPort.TXOctets = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("error frames"))
                                {
                                    tmpPort.TXErrorFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                }
                                if (line.Contains("discard frames"))
                                {
                                    tmpPort.TXDiscardFrames = long.Parse(Regex.Split(line, "  ")[1]);
                                    portsArrayList.Add(tmpPort);
                                    break;
                                }
                            }
                        }

                        // connected cable info
                        if (line.Contains("identifier"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).identifier = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("cable/ module type"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).cableModuleType = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("ethernet speed and type"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).ethernetSpeedAndType = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("vendor"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).vendor = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("cable_length"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).cableLength = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("part number"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).partNumber = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("revision"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).revision = Regex.Split(line, ":")[1];
                        }
                        if (line.Contains("serial number"))
                        {
                            ((PortInfoETHFields)portsArrayList[index]).serialNumber = Regex.Split(line, ":")[1];
                            // increase the index 
                            index++;
                        }
                        if (line.Contains("Negotiation"))
                        {
                            sr.Dispose();
                            return;
                        }
                    }
                    catch
                    {
                    }
                }
            }
            catch 
            {
            }
            sr.Dispose();
        }
        //
        //----------------------------------------------------
        //
        public bool getTimeoutState()
        {
            return timeouts;
        }
    }
}
